﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Xml;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.BIM;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.DataModel
{
	public class SprinklerCalOperate
	{
		public SprinklerCalOperate()
		{
			if (!File.Exists(this.markPath))
			{
				File.Copy(Product.InstallLocation + "\\Data\\HYMarking.xml", this.markPath, true);
			}
			this.xmlDoc.Load(this.markPath);
			if (!File.Exists(this.dataSource))
			{
				File.Copy(Product.InstallLocation + "\\Data\\HYMEPDatasource.db", this.dataSource, true);
			}
			SQLiteDataOperate.SetDataSource(this.dataSource);
		}

		public int GetSprinklerPara(string paraName)
		{
			int result = 0;
			XmlNode xmlNode = this.xmlDoc.SelectSingleNode("Marking");
			XmlNode xmlNode2 = xmlNode.SelectSingleNode(paraName);
			if (xmlNode2 != null)
			{
				result = Convert.ToInt32(xmlNode2.InnerText);
			}
			return result;
		}

		public void GetSprinklerMarkPara(string paraName, ref double value)
		{
			try
			{
				XmlNode xmlNode = this.xmlDoc.SelectSingleNode("Marking");
				XmlNode xmlNode2 = xmlNode.SelectSingleNode(paraName);
				if (xmlNode2 != null)
				{
					value = Convert.ToDouble(xmlNode2.InnerText);
				}
			}
			catch (Exception ex)
			{
				ex.ToString();
				value = 0.0;
			}
		}

		public void GetSprinklerMarkPara(string paraName, ref bool value)
		{
			try
			{
				XmlNode xmlNode = this.xmlDoc.SelectSingleNode("Marking");
				XmlNode xmlNode2 = xmlNode.SelectSingleNode(paraName);
				if (xmlNode2 != null)
				{
					value = Convert.ToBoolean(xmlNode2.InnerText);
				}
			}
			catch (Exception ex)
			{
				ex.ToString();
				value = true;
			}
		}

		public void SaveSprinklerPara(string value, string paraName)
		{
			XmlNode xmlNode = this.xmlDoc.SelectSingleNode("Marking");
			XmlNode xmlNode2 = xmlNode.SelectSingleNode(paraName);
			if (xmlNode2 != null)
			{
				xmlNode2.InnerText = value;
			}
			else
			{
				XmlElement xmlElement = XMLOperating.AddElement(this.xmlDoc, this.markPath, "Marking", paraName);
				xmlElement.InnerText = value;
				xmlNode.AppendChild(xmlElement);
			}
			this.xmlDoc.Save(this.markPath);
		}

		public void SaveSprinklerPara(double value, string paraName)
		{
			XmlNode xmlNode = this.xmlDoc.SelectSingleNode("Marking");
			XmlNode xmlNode2 = xmlNode.SelectSingleNode(paraName);
			if (xmlNode2 != null)
			{
				xmlNode2.InnerText = value.ToString();
			}
			else
			{
				XmlElement xmlElement = XMLOperating.AddElement(this.xmlDoc, this.markPath, "Marking", paraName);
				xmlElement.InnerText = value.ToString();
				xmlNode.AppendChild(xmlElement);
			}
			this.xmlDoc.Save(this.markPath);
		}

		public List<Fire_Danger> GetListFireDanger()
		{
			List<Fire_Danger> list = new List<Fire_Danger>();
			List<Fire_Danger> result;
			try
			{
				string sqlStr = "select * from [Fire_Danger]";
				DataTable dataTable = SQLiteDataOperate.ExecQuery(sqlStr);
				foreach (object obj in dataTable.Rows)
				{
					DataRow dataRow = (DataRow)obj;
					list.Add(new Fire_Danger
					{
						Id = Convert.ToInt32(dataRow["id"]),
						DangerLevel = Convert.ToString(dataRow["wxdj"]),
						MaxDia = Convert.ToInt32(dataRow["maxdn"]),
						Distance = Convert.ToDouble(dataRow["dis"])
					});
				}
				List<string> list2 = new List<string>
				{
					"轻危险等级",
					"中危险等级I",
					"中危险等级II",
					"严重危险等级I",
					"严重危险等级II",
					"仓库危险等级I",
					"仓库危险等级II",
					"仓库危险等级III"
				};
				for (int i = 0; i < list.Count; i++)
				{
					list[i].DangerLevel = list2[i];
				}
				result = list;
			}
			catch (MissingFieldException)
			{
				result = null;
			}
			return result;
		}

		public Fire_PtDn GetFirePtDn(int id)
		{
			Fire_PtDn fire_PtDn = new Fire_PtDn();
			try
			{
				string sqlStr = string.Format("select * from [Fire_PtDN] where id={0}", id);
				DataTable dataTable = SQLiteDataOperate.ExecQuery(sqlStr);
				if (dataTable != null && dataTable.Rows.Count > 0)
				{
					fire_PtDn.Id = Convert.ToInt32(dataTable.Rows[0]["id"]);
					fire_PtDn.DangerId = Convert.ToInt32(dataTable.Rows[0]["dangerid"]);
					fire_PtDn.Diameter = Convert.ToInt32(dataTable.Rows[0]["DN"]);
					fire_PtDn.SprinklerNum = Convert.ToInt32(dataTable.Rows[0]["ptnum"]);
					fire_PtDn.AddInfo = AddSprinklerDiameter.NO;
				}
			}
			catch (Exception)
			{
				fire_PtDn = null;
				throw;
			}
			return fire_PtDn;
		}

		public List<Fire_PtDn> GetListFirePtDn(int danId)
		{
			List<Fire_PtDn> list = new List<Fire_PtDn>();
			List<Fire_PtDn> result;
			try
			{
				string sqlStr = string.Format("select * from [Fire_PtDN] where dangerid={0}", danId);
				DataTable dataTable = SQLiteDataOperate.ExecQuery(sqlStr);
				foreach (object obj in dataTable.Rows)
				{
					DataRow dataRow = (DataRow)obj;
					list.Add(new Fire_PtDn
					{
						Id = Convert.ToInt32(dataRow["id"]),
						DangerId = Convert.ToInt32(dataRow["dangerid"]),
						Diameter = Convert.ToInt32(dataRow["DN"]),
						SprinklerNum = Convert.ToInt32(dataRow["ptnum"]),
						AddInfo = AddSprinklerDiameter.NO
					});
				}
				result = list;
			}
			catch (MissingFieldException)
			{
				result = null;
			}
			return result;
		}

		public bool ExecuteCmdPT(string sql)
		{
			return SQLiteDataOperate.ExecuteCommand(sql);
		}

		public void GetSprinklerKValue(string elemId, List<PipeInfo> listInfo, ref double sNum, bool beHaveKValue)
		{
			List<string> list = new List<string>();
			foreach (PipeInfo pipeInfo in listInfo)
			{
				string parentId = pipeInfo.ParentId;
				if (parentId == elemId)
				{
					list.Add(pipeInfo.ElemId);
					Element element = pipeInfo.ENode.Element;
					if (element is FamilyInstance)
					{
						int integerValue = element.Category.Id.IntegerValue;
						if (integerValue == -2008099)
						{
							FamilySymbol symbol = (element as FamilyInstance).Symbol;
							Parameter parameter = symbol.GetParameter(BuiltInParameter.RBS_FP_SPRINKLER_K_FACTOR_PARAM);
							if (parameter == null || !parameter.HasValue || !beHaveKValue)
							{
								sNum += 80.0;
							}
							else
							{
								double num = parameter.AsDouble();
								if (num <= 0.0)
								{
									sNum += 80.0;
								}
								else
								{
									sNum += num;
								}
							}
						}
					}
				}
			}
			if (list.Count > 0)
			{
				foreach (string elemId2 in list)
				{
					this.GetSprinklerKValue(elemId2, listInfo, ref sNum, beHaveKValue);
				}
			}
		}

		public void GetSprinklerNum(string elemId, List<PipeInfo> listInfo, ref int sNum)
		{
			List<string> list = new List<string>();
			foreach (PipeInfo pipeInfo in listInfo)
			{
				string parentId = pipeInfo.ParentId;
				if (parentId == elemId)
				{
					list.Add(pipeInfo.ElemId);
					Element element = pipeInfo.ENode.Element;
					if (element is FamilyInstance)
					{
						int integerValue = element.Category.Id.IntegerValue;
						if (integerValue == -2008099)
						{
							sNum++;
						}
					}
				}
			}
			if (list.Count > 0)
			{
				foreach (string elemId2 in list)
				{
					this.GetSprinklerNum(elemId2, listInfo, ref sNum);
				}
			}
		}

		public void AddElementNode(ElementNode eNode, ref List<PipeInfo> listInfo, ref int id, int dangerId, double K)
		{
			if (eNode == null)
			{
				return;
			}
			PipeInfo pipeInfo = new PipeInfo();
			if (id == 0)
			{
				pipeInfo.ParentId = "";
			}
			else
			{
				pipeInfo.ParentId = eNode.Preview.Element.Id.ToString();
			}
			id++;
			string sqlStr = "select * from [Fire_Danger] where id=" + dangerId;
			DataTable dataTable = SQLiteDataOperate.ExecQuery(sqlStr);
			Fire_Danger fire_Danger = new Fire_Danger();
			foreach (object obj in dataTable.Rows)
			{
				DataRow dataRow = (DataRow)obj;
				fire_Danger.DangerLevel = Convert.ToString(dataRow["wxdj"]);
				fire_Danger.Distance = Convert.ToDouble(dataRow["dis"]);
			}
			if (eNode.Element.GetParameter("危险等级") != null)
			{
				eNode.Element.GetParameter("危险等级").Set(fire_Danger.DangerLevel);
			}
			if (eNode.Element.GetParameter("喷淋半径") != null)
			{
				eNode.Element.GetParameter("喷淋半径").Set(UnitConvert.CovertToAPI(fire_Danger.Distance * 1000.0, (Autodesk.Revit.DB.DisplayUnitType)2));
			}
			pipeInfo.ElemId = eNode.Element.Id.ToString();
			pipeInfo.ENode = eNode;
			listInfo.Add(pipeInfo);
			this.AddElementNode(eNode.Next, ref listInfo, ref id, dangerId, K);
			if (eNode.SubElementNode != null)
			{
				foreach (ElementNode eNode2 in eNode.SubElementNode)
				{
					this.AddElementNode(eNode2, ref listInfo, ref id, dangerId, K);
				}
			}
		}

		public void ChangeFittingDiameter(ElementNode eNode)
		{
			if (eNode == null || eNode.Element == null || !eNode.Element.IsValidObject)
			{
				return;
			}
			if (eNode.Element is FamilyInstance && (eNode.Element as FamilyInstance).MEPModel != null && (eNode.Element as FamilyInstance).MEPModel is MechanicalFitting)
			{
				FamilyInstance elem = eNode.Element as FamilyInstance;
				MechanicalFitting mechanicalFitting = (eNode.Element as FamilyInstance).MEPModel as MechanicalFitting;
                if ((int)mechanicalFitting.PartType == 5 || (int)mechanicalFitting.PartType == 6 || (int)mechanicalFitting.PartType == 8)
				{
					List<Connector> elementAllConnector = YJKRevitTools.GetElementAllConnector(elem);
					IList<List<Connector>> list = this.GroupConnectors(elementAllConnector);
					double num = 0.0;
					List<Connector> list2 = null;
					foreach (List<Connector> list3 in list)
					{
						num = 0.0;
						list2 = list3;
						foreach (Connector connector in list2)
						{
							Pipe connectedPipe = this.GetConnectedPipe(connector);
							if (connectedPipe != null)
							{
								double num2 = connectedPipe.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
								num = ((num2 > num) ? num2 : num);
							}
						}
						if (num > 0.0)
						{
							foreach (Connector connector2 in list2)
							{
								connector2.Radius = num / 2.0;
							}
						}
					}
				}
			}
			this.ChangeFittingDiameter(eNode.Next);
			if (eNode.SubElementNode != null && eNode.SubElementNode.Count > 0)
			{
				foreach (ElementNode eNode2 in eNode.SubElementNode)
				{
					this.ChangeFittingDiameter(eNode2);
				}
			}
		}

		private IList<List<Connector>> GroupConnectors(List<Connector> connList)
		{
			IList<List<Connector>> list = new List<List<Connector>>();
			if (connList == null || connList.Count <= 0)
			{
				return list;
			}
			for (int i = 0; i < connList.Count - 1; i++)
			{
				bool flag = false;
				List<Connector> list2 = new List<Connector>();
				for (int j = i + 1; j < connList.Count; j++)
				{
					if (connList[i].CoordinateSystem.BasisZ.IsAlmostEqualTo(-1.0 * connList[j].CoordinateSystem.BasisZ))
					{
						list2.Add(connList[i]);
						list2.Add(connList[j]);
						flag = true;
						break;
					}
				}
				if (!flag && !this.CheckContains(list, connList[i]))
				{
					list2.Add(connList[i]);
				}
				if (list2.Count > 0)
				{
					list.Add(list2);
				}
			}
			return list;
		}

		private bool CheckContains(IList<List<Connector>> groupConns, Connector conn)
		{
			bool result = false;
			if (groupConns == null || conn == null)
			{
				return result;
			}
			foreach (List<Connector> list in groupConns)
			{
				if (list.Contains(conn))
				{
					result = true;
					break;
				}
			}
			return result;
		}

		private Pipe GetConnectedPipe(Connector connector)
		{
			if (connector == null)
			{
				return null;
			}
			Connector connectedConnector = connector.GetConnectedConnector();
			if (connectedConnector == null || connectedConnector.Owner == null)
			{
				return null;
			}
			if (connectedConnector.Owner is Pipe)
			{
				return connectedConnector.Owner as Pipe;
			}
			if (connectedConnector.Owner is FamilyInstance && (connectedConnector.Owner as FamilyInstance).MEPModel != null)
			{
				MechanicalFitting mechanicalFitting = (connectedConnector.Owner as FamilyInstance).MEPModel as MechanicalFitting;
                if ((int)mechanicalFitting.PartType == 7)
				{
					foreach (object obj in (connectedConnector.Owner as FamilyInstance).MEPModel.ConnectorManager.Connectors)
					{
						Connector connector2 = (Connector)obj;
						if (connector2 != connectedConnector && !connector2.Origin.IsAlmostEqualTo(connectedConnector.Origin, 1E-06))
						{
							return this.GetConnectedPipe(connector2);
						}
					}
				}
			}
			return null;
		}

		public IList<Element>[] ChangeDiameter(ElementNode eNode, List<Fire_PtDn> listPtNum, int maxDiameter, int dangerId, double K, int minDiameter, bool beHaveKValue)
		{
			IList<Element>[] array = new IList<Element>[]
			{
				new List<Element>(),
				new List<Element>()
			};
			List<PipeInfo> list = new List<PipeInfo>();
			int num = 0;
			int num2 = 0;
			this.AddElementNode(eNode, ref list, ref num, dangerId, K);
			foreach (PipeInfo pipeInfo in list)
			{
				Pipe pipe = pipeInfo.ENode.Element as Pipe;
				if (pipe != null)
				{
					double kValue = 0.0;
					this.GetSprinklerKValue(pipe.Id.ToString(), list, ref kValue, beHaveKValue);
					int sprinklerNumber = this.GetSprinklerNumber(kValue);
					if (sprinklerNumber < 1)
					{
						array[0].Add(pipeInfo.ENode.Element);
					}
					else
					{
						bool bConnSprinkler = this.PipeConnSprinkler(pipe);
						int pdiameterBySprinklers = this.GetPDiameterBySprinklers(sprinklerNumber, listPtNum, maxDiameter, K, bConnSprinkler, minDiameter);
						Parameter parameter = pipe.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
						if (parameter.Set((double)pdiameterBySprinklers / 304.8))
						{
							num2++;
						}
						array[1].Add(pipeInfo.ENode.Element);
					}
				}
			}
			YJKMessageBox.Show("共确定并修改" + num2 + "条水管。");
			return array;
		}

		public List<Element> GetTagPipes(ElementNode eNode, int dangerId, double K, bool beHaveKValue)
		{
			List<Element> list = new List<Element>();
			List<PipeInfo> list2 = new List<PipeInfo>();
			int num = 0;
			this.AddElementNode(eNode, ref list2, ref num, dangerId, K);
			foreach (PipeInfo pipeInfo in list2)
			{
				Pipe pipe = pipeInfo.ENode.Element as Pipe;
				if (pipe != null)
				{
					double kValue = 0.0;
					this.GetSprinklerKValue(pipe.Id.ToString(), list2, ref kValue, beHaveKValue);
					int sprinklerNumber = this.GetSprinklerNumber(kValue);
					if (sprinklerNumber >= 1)
					{
						list.Add(pipeInfo.ENode.Element);
					}
				}
			}
			return list;
		}

		private int GetSprinklerNumber(double kValue)
		{
			double num = kValue / 80.0;
			int num2 = Convert.ToInt32(Math.Truncate(num));
			if (num - (double)num2 > 0.0)
			{
				num2++;
			}
			return num2;
		}

		private bool PipeConnSprinkler(Pipe pipe)
		{
			bool result = false;
			List<Connector> pipeConnConnector = YJKRevitTools.GetPipeConnConnector(pipe);
			foreach (Connector connector in pipeConnConnector)
			{
				Connector connectConnector = YJKRevitTools.GetConnectConnector(connector);
				if (connectConnector.Owner.Category.Id.IntegerValue == -2008099)
				{
					result = true;
				}
			}
			return result;
		}

		public int GetPDiameterBySprinklers(int spNum, List<Fire_PtDn> listPtNum, int maxDia, double K, bool bConnSprinkler, int minDiameter)
		{
			int num = 0;
			listPtNum.Sort((Fire_PtDn first, Fire_PtDn second) => first.SprinklerNum.CompareTo(second.SprinklerNum));
			int count = listPtNum.Count;
			if (spNum >= listPtNum[count - 1].SprinklerNum)
			{
				num = listPtNum[count - 1].Diameter;
			}
			else
			{
				for (int i = 0; i < count - 1; i++)
				{
					if (spNum == listPtNum[i].SprinklerNum)
					{
						num = listPtNum[i].Diameter;
					}
					else if (spNum > listPtNum[i].SprinklerNum && spNum < listPtNum[i + 1].SprinklerNum)
					{
						num = listPtNum[i + 1].Diameter;
					}
				}
			}
			if (num >= maxDia)
			{
				return maxDia;
			}
			if (K == 320.0)
			{
				if (num < 40 && !bConnSprinkler)
				{
					return 40;
				}
			}
			else if (num < 0 && minDiameter != 0 && !bConnSprinkler)
			{
				return minDiameter;
			}
			return num;
		}

		private string markPath = Path.Combine(Product.UserDataLocation, "HYMarking.xml");

		private string dataSource = Path.Combine(Product.UserDataLocation, "HYMEPDatasource.db");

		private XmlDocument xmlDoc = new XmlDocument();
	}
}
